package com.myphoto.base.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

/**
 * 此类用于存放无数据库操作的通用方法
 */
public class UserFun {

	//中文(大陆)计数单位
	static final String[] unitCN = new String[]{"京","","","","万兆","","","","兆","","","","万亿","","","","亿","","","","万","","","",""};

	/**
	 * 新建Cookie对象(无加密，根路径)
	 * @最后修改人	方安伦
	 * @修改时间	2014-12-12 下午3:12:38
	 * @param name
	 * @param value
	 * @return
	 */
	public static Cookie newCookie(String name, String value){
		Cookie randomCookie = new Cookie(name, value);
		randomCookie.setPath("/");
		return randomCookie;
	}

	public static int compareDatesDay(Date date1,Date date2){
		int days = 0;
		try {
			days = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return days;
	}
	
	/**
	 * 获取一定位数的随机字符串(A-z0-9)
	 * @最后修改人	方安伦
	 * @修改时间	2014-12-22 下午3:58:20
	 * @param len
	 * @return
	 */
	public static String getRandomString(int len){
		//定义可选择的字符
		char[] chars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h',
			'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
			'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
		Random random = new Random();
		StringBuffer buffer = new StringBuffer();
		for(int i=0;i<len;i++){
			buffer.append(chars[random.nextInt(chars.length)]);
		}
		return buffer.toString();
	}
	
	/**
	 * 获取通过代理的用户的真实IP地址
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
	    String ip = request.getHeader("x-forwarded-for");  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("WL-Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getRemoteAddr();  
	    }  
	    return ip;  
	}
	
	/**
	* 把一个double数值转换为带有中文单位的字符串
	* @author 雷日初
	* @date 2020年1月17日 上午09:56:52
	* @param num 待转换的double数值
	* @param digit 添加计量单位后要保留的最长小数位数（注：小于一万的数值，原小数部分将全部保留）
	* 如：10000.1234转换得“1万”，9999.1234转换得“9999.1234”
	* @return 带中文“兆/亿/万”计量单位的字符串,在不超过指定保留的最长小数位数的情况下，再截去结尾连续为0的小数位
	*/
	public static String formartNumByCnUnit(double num, int digit){
		if(digit<0){
			digit = 0;
		}
		String numberStr = (new BigDecimal(String.valueOf(num))).toPlainString();
		String ends = "";
		char[] splits = null;
		if(numberStr.indexOf(".")>-1){
			splits = (numberStr.substring(0,numberStr.indexOf("."))).toCharArray();
			char[] ends0 = (numberStr.substring(numberStr.indexOf(".")+1, numberStr.length())).toCharArray();
			for(int i=ends0.length-1;i>=0;i--){
				if(ends0[i] != '0'){
					for(int j=0;j<=i;j++){
						ends += ends0[j];
					}
					break;
				}
			}
		}else{
			splits = numberStr.toCharArray();
		}
		StringBuffer retStr = new StringBuffer();
		String unit = "";
		for(int i=0;i<splits.length;i++){
			if(splits.length>4 && (unitCN.length-splits.length+i)%4==0 && unit.length()==0){
				unit = unitCN[unitCN.length-splits.length+i];
				retStr.append(splits[i]);
				String others = "";
				for(int j=i+1;j<splits.length && j-i<=digit+1;j++){
					others += splits[j];
				}
				if(others.length()>0){
					int oth = Integer.parseInt(others);
					if(oth>0){
						if(others.length()>digit){
							double tmps = (Math.round(oth*Math.pow(10,-1)))*Math.pow(10,-digit);
							others = ((tmps + "").split("\\.")).length>1?((tmps + "").split("\\."))[1]:"";
							others = others.length()>=digit ? others.substring(0, digit) : others;
							if(tmps >= 1){
								int tmpInt = Integer.parseInt(retStr.toString()) + 1;
								if(tmpInt==10000){
									retStr = new StringBuffer("1");
									unit = unitCN[unitCN.length-splits.length+i-4];
								}else{
									retStr = new StringBuffer(tmpInt+"");
								}
							}
						}
						while(others.endsWith("0")){
							others = others.substring(0, others.length()-1);
						}
						others = others.length() == 0 ? "" : "." + others;
					}else{
						others = "";
					}
				}
				retStr.append(others + unit);
				break;
			}else{
				retStr.append(splits[i]);
			}
		}
		if(unit.length()==0 && ends.length()>0){
			retStr.append("." + ends);
		}
		return retStr.toString();
	}

	/**
	* @description 从listA里删除listB里有的数据
	* @author 方安伦
	* @date 2021/5/27 10:32
	* @param listA
	* @param listB
	* @return List<String>
	 **/
	public static List<String> listrem(List<String> listA, List<String> listB){
		for (Iterator<String> itA = listA.iterator(); itA.hasNext();){
			String temp = itA.next();
			// itA.next() 只能在外层循环里面调用1次
			for (int i = 0; i < listB.size(); i++){
				if (temp.equals(listB.get(i))){
					itA.remove();
					break;
				}
			}
		}
		return listA;
	}

	public static int getRandomInt(int min,int max){
		return (int)(min+Math.random()*(max-min+1));
	}

	public static String getUUID32(){
		String uuid = UUID.randomUUID().toString(); //转化为String对象
		uuid = uuid.replace("-", "");//因为UUID本身为32位只是生成时多了“-”，所以将它们去除就可
		return uuid;
	}

	public static String getStringNoNullTrim(String str) {
		return str != null && !"null".equals(str.trim()) ? str.trim() : "";
	}

	/**
	* @description 根据异常对象，取得异常堆栈信息
	* @author 方安伦
	* @date 2021/11/22 17:14
	* @param e
	* @return String
	 **/
	public static String getStackTraceForHtml(Exception e, int linenum) {
		String returnStr = "";
		int lineCount = 0;
		int moreInt = 0;
		int causeLength = 0;
		StringBuffer buf = new StringBuffer();
		StackTraceElement[] elements = e.getStackTrace();
		Throwable causeThrowable = e.getCause();
		StackTraceElement[] elementsCause = null;
		if (causeThrowable != null) {
			elementsCause = causeThrowable.getStackTrace();
			causeLength = elementsCause.length;
		}

		if (lineCount >= linenum && linenum != -1) {
			if (moreInt == 0) {
				moreInt = elements.length + causeLength;
				buf.append("<br>&nbsp;&nbsp;&nbsp;&nbsp;... " + moreInt + " more");
			}
		} else {
			buf.append(e.getClass().getName() + ":" + getStringNoNullTrim(e.getMessage()));
			++lineCount;
		}

		int i;
		String opsition;
		for(i = 0; i < elements.length; ++i) {
			if (lineCount >= linenum && linenum != -1) {
				if (moreInt == 0) {
					moreInt = elements.length - i + causeLength;
					buf.append("<br>&nbsp;&nbsp;&nbsp;&nbsp;... " + moreInt + " more");
				}
			} else {
				opsition = "Unknown Source";
				if (elements[i].getFileName() != null) {
					opsition = elements[i].getFileName() + ":" + elements[i].getLineNumber();
				}

				buf.append("<br>&nbsp;&nbsp;&nbsp;&nbsp;at " + elements[i].getClassName() + "." + elements[i].getMethodName() + "(" + opsition + ")");
				++lineCount;
			}
		}

		if (causeThrowable != null) {
			if (lineCount >= linenum && linenum != -1) {
				if (moreInt == 0) {
					moreInt = causeLength;
					buf.append("<br>&nbsp;&nbsp;&nbsp;&nbsp;... " + causeLength + " more");
				}
			} else {
				buf.append("<br>Caused by:" + causeThrowable.getClass().getName() + ":" + getStringNoNullTrim(causeThrowable.getMessage()) + "<br>");
				lineCount += 2;
			}
		}

		if (causeThrowable != null) {
			for(i = 0; i < causeLength; ++i) {
				if (lineCount >= linenum && linenum != -1) {
					if (moreInt == 0) {
						moreInt = causeLength - i;
						buf.append("<br>&nbsp;&nbsp;&nbsp;&nbsp;... " + moreInt + " more");
					}
				} else {
					opsition = "Unknown Source";
					if (elementsCause[i].getFileName() != null) {
						opsition = elementsCause[i].getFileName() + ":" + elementsCause[i].getLineNumber();
					}

					buf.append("<br>&nbsp;&nbsp;&nbsp;&nbsp;at " + elementsCause[i].getClassName() + "." + elementsCause[i].getMethodName() + "(" + opsition + ")");
					++lineCount;
				}
			}
		}

		returnStr = buf.toString();
		returnStr = returnStr.trim();
		return returnStr;
	}

	/**
	* @description 根据属性，调用get方法
	* @author 方安伦
	* @date 2021/12/10 14:30
	 **/
	public static Object doGetMethod(Object ob , String name)throws Exception{
		Method[] m = ob.getClass().getMethods();
		for(int i = 0;i < m.length;i++){
			if(("get"+name).toLowerCase().equals(m[i].getName().toLowerCase())){
				return m[i].invoke(ob);
			}
		}
		return null;
	}
}
